﻿using CqCore.Logging;
using CqCore.Redis;
using RedisService.Options;
using ServiceStack.Redis;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RedisService
{
    public class RedisService : IRedisService
    {
        private readonly RedisOption redisOption;
        private readonly ILogRecorder<RedisService> logRecorder;

        public RedisService(RedisOption redisOption, ILogRecorder<RedisService> logRecorder)
        {
            this.redisOption = redisOption;
            this.logRecorder = logRecorder;
        }


        public async Task<bool> AddItemToListT<T>(string key, T value)
        {
            using (var client = new RedisClient(redisOption.Host, redisOption.Port) { Password = redisOption.Password })
            {
                if (client.Get<List<T>>(key) == null)
                {
                    client.Set<List<T>>(key, new List<T>());
                }
                var list = client.Get<List<T>>(key);
                list.Add(value);
               return await Task.FromResult(client.Set<List<T>>(key, list));
            }
        }

        public async Task<T> Get<T>(string key)
        {
            using (var client = new RedisClient(redisOption.Host, redisOption.Port) { Password = redisOption.Password })
            {
                return await Task.FromResult(client.Get<T>(key));
            }
        }

        public async Task<T> GetLasterItemFromList<T>(string key)
        {
            using (var client = new RedisClient(redisOption.Host, redisOption.Port) { Password = redisOption.Password })
            {
                return await Task.FromResult(client.Get<List<T>>(key).LastOrDefault());
            }
        }

        public async Task<T> GetOrSet<T>(string key, Func<Task<T>> func, int hours = 24)
        {
            try
            {
                T result = await this.Get<T>(key);
                if (result == null)
                {
                    result = await func();
                    if (result != null)
                    {
                        if (result is ICollection)
                        {
                            var temp = result as ICollection;
                            if (temp.Count > 0)
                            {
                               await this.Set<T>(key, result, DateTime.Now.AddHours(hours));
                            }
                        }
                        else
                        {
                            await this.Set<T>(key, result, DateTime.Now.AddHours(hours));
                        }

                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                logRecorder.Error(new EventData()
                {
                    Type = "RedisService.GetOrSet",
                    Message = "redis读取缓存",
                    Labels = {
                        ["Error"]=ex.Message
                    }
                });
                //直接返回数据库数据，防止业务程序走不通
                return await func();
            }
        }

        public async Task<bool> Remove(string key)
        {
            using (var client = new RedisClient(redisOption.Host, redisOption.Port) { Password = redisOption.Password })
            {
                return await Task.FromResult(client.Remove(key));
            }
        }

        public async Task<bool> RemoveList(List<string> keys)
        {
            using (var client = new RedisClient(redisOption.Host, redisOption.Port) { Password = redisOption.Password })
            {
                client.RemoveAll(keys);
                return await Task.FromResult(true);
            }
        }

        public async Task<bool> Set<T>(string token, T obj, DateTime expressTime)
        {
            using (var client = new RedisClient(redisOption.Host, redisOption.Port) { Password = redisOption.Password })
            {
                return await Task.FromResult(client.Set<T>(token, obj, expressTime));
            }
        }
    }
}
